#ifndef __INCLUDED_CRL_PARAMETER_ATOMIC_H_
#error "CRL_ParameterAtomic.hpp must not be used directly. Use CRL_ParameterAtomic.h instead."
#else
#ifndef __INCLUDED_CRL_PARAMETER_ATOMIC_HPP__
#define __INCLUDED_CRL_PARAMETER_ATOMIC_HPP__

#define TUPLE_ATOMIC_TYPE ITupleParameterAtomic<TType>

#include "CBL_Debug.h"

// ---------------------------------------------------------------------------------------------------------------------
//	IParameterAtomic
// ---------------------------------------------------------------------------------------------------------------------

inline IParameterAtomic::IParameterAtomic(EValueType _ValueType, uint16 _NumRegisters)
	: m_NumRegisters(_NumRegisters)
	, m_ValueType(_ValueType)
{
}

// ---------------------------------------------------------------------------------------------------------------------
//	IMatrix4x4ParameterAtomic
// ---------------------------------------------------------------------------------------------------------------------

inline IMatrix4x4ParameterAtomic::IMatrix4x4ParameterAtomic(uint16 _NumMatrices)
	: IParameterAtomic(IParameterAtomic::MatrixType, _NumMatrices * 4)
{
	m_ValueArray = new Math::Float4x4[_NumMatrices];
}

// ---------------------------------------------------------------------------------------------------------------------

inline IMatrix4x4ParameterAtomic::~IMatrix4x4ParameterAtomic()
{
	delete[] m_ValueArray;
}

// ---------------------------------------------------------------------------------------------------------------------

CB_FORCEINLINE void CB_INLINE_ATTR IMatrix4x4ParameterAtomic::SetValue(Math::Float4x4& _rValue, uint16 _Index)
{
	Debug::Assert(CB_DEBUG_INFO(_Index < m_NumRegisters/4));
	m_ValueArray[_Index] = _rValue;
}

// ---------------------------------------------------------------------------------------------------------------------

CB_FORCEINLINE void CB_INLINE_ATTR IMatrix4x4ParameterAtomic::SetValues(Math::Float4x4* _pValues, uint16 _Count)
{
	Debug::Assert(CB_DEBUG_INFO(_Count < m_NumRegisters/4));
	memcpy(m_ValueArray, _pValues, _Count * sizeof(Math::Float4x4));
}

// ---------------------------------------------------------------------------------------------------------------------
//	CTupleParameterAtomic
// ---------------------------------------------------------------------------------------------------------------------

template <>
inline ITupleParameterAtomic<float>::ITupleParameterAtomic(uint16 _NumTuples) 
	: IParameterAtomic(IParameterAtomic::FloatType, _NumTuples) 
{
	m_ValueArray = new C4Component[m_NumRegisters];
}

// ---------------------------------------------------------------------------------------------------------------------

template <>
inline ITupleParameterAtomic<int>::ITupleParameterAtomic(uint16 _NumTuples) 
	: IParameterAtomic(IParameterAtomic::IntType, _NumTuples) 
{
	m_ValueArray = new C4Component[m_NumRegisters];
}

// ---------------------------------------------------------------------------------------------------------------------

template <>
inline ITupleParameterAtomic<bool>::ITupleParameterAtomic(uint16 _NumTuples) 
	: IParameterAtomic(IParameterAtomic::BoolType, _NumTuples) 
{
	m_ValueArray = new C4Component[m_NumRegisters];
}

// ---------------------------------------------------------------------------------------------------------------------

template <typename TType>
inline TUPLE_ATOMIC_TYPE::~ITupleParameterAtomic()
{
	delete[] m_ValueArray;
}

// ---------------------------------------------------------------------------------------------------------------------

template <typename TType>
CB_FORCEINLINE void CB_INLINE_ATTR TUPLE_ATOMIC_TYPE::SetValue(const typename TUPLE_ATOMIC_TYPE::C1Component& _rValue, uint16 _Index)					
{ 
	Debug::Assert(CB_DEBUG_INFO(_Index < m_NumRegisters));
	m_ValueArray[_Index].m_X = _rValue;
}

// ---------------------------------------------------------------------------------------------------------------------

template <typename TType>
CB_FORCEINLINE void CB_INLINE_ATTR TUPLE_ATOMIC_TYPE::SetValue(const typename TUPLE_ATOMIC_TYPE::C2Component& _rValue, uint16 _Index)
{ 
	Debug::Assert(CB_DEBUG_INFO(_Index < m_NumRegisters));
	m_ValueArray[_Index].m_X = _rValue.m_X;
	m_ValueArray[_Index].m_Y = _rValue.m_Y;
}

// ---------------------------------------------------------------------------------------------------------------------

template <typename TType>
inline void TUPLE_ATOMIC_TYPE::SetValue(const typename TUPLE_ATOMIC_TYPE::C3Component& _rValue, uint16 _Index)
{ 
	Debug::Assert(CB_DEBUG_INFO(_Index < m_NumRegisters));
	m_ValueArray[_Index].m_X = _rValue.m_X;
	m_ValueArray[_Index].m_Y = _rValue.m_Y;
	m_ValueArray[_Index].m_Z = _rValue.m_Z;
}

// ---------------------------------------------------------------------------------------------------------------------

template <typename TType>
CB_FORCEINLINE void CB_INLINE_ATTR TUPLE_ATOMIC_TYPE::SetValue(const typename TUPLE_ATOMIC_TYPE::C4Component& _rValue, uint16 _Index)
{ 
	Debug::Assert(CB_DEBUG_INFO(_Index < m_NumRegisters));
	m_ValueArray[_Index] = _rValue;
}

// ---------------------------------------------------------------------------------------------------------------------

template <typename TType>
CB_FORCEINLINE void CB_INLINE_ATTR TUPLE_ATOMIC_TYPE::SetValues(const typename TUPLE_ATOMIC_TYPE::C1Component* _pValues, uint16 _Count)					
{ 
	Debug::Assert(CB_DEBUG_INFO(_Count < m_NumRegisters * 4));
	memcpy(m_ValueArray, _pValues, _Count * sizeof(C1Component));
}

// ---------------------------------------------------------------------------------------------------------------------

template <typename TType>
CB_FORCEINLINE void CB_INLINE_ATTR TUPLE_ATOMIC_TYPE::SetValues(const typename TUPLE_ATOMIC_TYPE::C2Component* _pValues, uint16 _Count)
{ 
	Debug::Assert(CB_DEBUG_INFO(_Count < m_NumRegisters * 2));
	memcpy(m_ValueArray, _pValues, _Count * sizeof(C2Component));
}

// ---------------------------------------------------------------------------------------------------------------------

template <typename TType>
CB_FORCEINLINE void CB_INLINE_ATTR TUPLE_ATOMIC_TYPE::SetValues(const typename TUPLE_ATOMIC_TYPE::C4Component* _pValues, uint16 _Count)
{ 
	Debug::Assert(CB_DEBUG_INFO(_Count < m_NumRegisters));
	memcpy(m_ValueArray, _pValues, _Count * sizeof(C4Component));
}

#undef TUPLE_ATOMIC_TYPE

#endif
#endif